package com.mcxx.common;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.mcxx.modules.statistics.dao.read.StatisDataItemReadDao;
import com.mcxx.modules.statistics.entity.MemberInfoEntity;
import com.mcxx.modules.statistics.entity.StatisDataItemEntity;
import com.mcxx.modules.statistics.entity.StatisItemEntity;
import com.mcxx.util.AreaUtil;
import com.mcxx.util.CommonUtil;
import com.mcxx.util.Constant;
import com.yinhai.ta404.component.org.orguser.area.entity.TaAreaPo;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;


public class ReportExtendUtils {

    private final static org.slf4j.Logger logger = LoggerFactory.getLogger(ReportExtendUtils.class);


    public static List<StatisDataItemEntity> getResultListNotByDataItem(String month, String itemSetId, StatisItemEntity item,
                                                                        TaAreaPo curTaAreaPo,
                                                                        AreaUtil areaUtil,
                                                                        StatisDataItemReadDao statisDataItemReadDao
    ) {

        List<StatisDataItemEntity> paList = new ArrayList<>();
        Map<String, String> params = new HashMap<>();
        params.put("bizType", item.getBusinessType());
        params.put("standType", item.getExceptionalPovertyType());
        params.put("yearMonth", month);
        params.put("areaCode", areaUtil.getValidCode(curTaAreaPo.getAreaCode(), curTaAreaPo.getAreaLevel()));

        logger.info("开始查询当前条件下的在保复查业务数据， 参数params={}",params);
        List<Map<String, String>> resultList = statisDataItemReadDao.queryStaticsItemSpecial(params);
        logger.info("查询当前条件下的在保复查业务数据结束， 结果共{}条",resultList.size());
        if (resultList.isEmpty()) {
            return paList;
        }

        List<String> orderIds = resultList.stream().map(e -> e.get("ORDERID")).collect(toList());

        List<String> familyIds = resultList.stream().map(e -> e.get("FAMILYID")).collect(toList());


        List<MemberInfoEntity> members = new ArrayList<>();
        if (familyIds.size() > 512) {
            List<List<String>> subList = Lists.partition(familyIds,512);
            List<List<String>> subList1 = Lists.partition(orderIds,512);
            for (int i = 0; i < subList1.size(); i++) {
                List<MemberInfoEntity> subLastOrderList = statisDataItemReadDao.getFamilyMemberByFamilyIdsAndOrderIds(subList.get(i), subList1.get(i));
                members.addAll(subLastOrderList);
            }
        } else {
            members = statisDataItemReadDao.getFamilyMemberByFamilyIdsAndOrderIds(familyIds, orderIds);
        }
        logger.info("根据familyId查找所有在保家庭成员结束， 共：{} 条",members.size());


//        List<Map<String, String>> lastOrderList = statisDataItemReadDao.queryLastOrderData(familyIds, month, item.getBusinessType());
        List<Map<String, String>> lastOrderList = new ArrayList<>();
        if (familyIds.size() > 1024) {
            List<List<String>> subList = Lists.partition(familyIds,1024);
            for (List<String> sub : subList) {
                List<Map<String, String>> subLastOrderList = statisDataItemReadDao.queryLastOrderData(sub, month, item.getBusinessType());
                lastOrderList.addAll(subLastOrderList);
            }
        } else {
            lastOrderList = statisDataItemReadDao.queryLastOrderData(familyIds, month, item.getBusinessType());
        }
        logger.info("根据familyId和当前时间查找在保的业务数据结束， 共：{} 条",lastOrderList.size());

        Map<String, List<Map<String, String>>> lastFamilyMap = lastOrderList.stream().collect(Collectors.groupingBy(e -> e.get("FAMILYID")));

        List<String> noRepeatFamilyList = familyIds.stream().distinct().collect(toList());
        List<Map<String, String>> finalOrderList = new ArrayList<>();
        for (String familyId: noRepeatFamilyList) {
            List<Map<String, String>> sameFamilyOrder = lastFamilyMap.get(familyId);

            Map<String, List<Map<String, String>>> startMonthMap = sameFamilyOrder.stream().collect(Collectors.groupingBy(e -> e.get("STARTMONTH")));
            if (startMonthMap.keySet().size() == 1) {
                finalOrderList.add(sameFamilyOrder.get(sameFamilyOrder.size() - 1));
            } else {
                finalOrderList.add(sameFamilyOrder.get(1));
            }
        }
        logger.info("查询 符合条件的复查数据的前一次业务数据 结束， 结果共{}条",finalOrderList.size());


        List<String> lastFamilyIds = finalOrderList.stream().map(e -> e.get("FAMILYID")).collect(toList());

        List<String> lastOrderIds = finalOrderList.stream().map(e -> e.get("ORDERID")).collect(toList());


        List<MemberInfoEntity> lastMembers = new ArrayList<>();
        if (lastOrderIds.size() > 512) {
            List<List<String>> subList1 = Lists.partition(lastFamilyIds,512);
            List<List<String>> subList2 = Lists.partition(lastOrderIds,512);
            for (int i = 0; i < subList1.size(); i++) {
                List<MemberInfoEntity> subLastOrderList = statisDataItemReadDao.getFamilyMemberByFamilyIdsAndOrderIds(subList1.get(i), subList2.get(i));
                lastMembers.addAll(subLastOrderList);
            }
        } else {
            lastMembers = statisDataItemReadDao.getFamilyMemberByFamilyIdsAndOrderIds(lastFamilyIds, lastOrderIds);
        }
        logger.info("根据lastFamilyIds和lastOrderIds查找在保的业务数据的前一次成员是结束， 共：{} 条",lastMembers.size());
        List<MemberInfoEntity> lastMembers1 = lastMembers;

        List<MemberInfoEntity> list = members.stream()
                .filter(itemMember -> !lastMembers1.stream().map(e -> e.getFamilyId() + "_" + e.getMemberId())
                        .collect(toList()).contains(itemMember.getFamilyId() + "_" + itemMember.getMemberId()))
                .collect(toList());
        logger.info("对比前后两次业务数据所有家庭成员，获取新增的家庭成员信息， 结果共{}条",list.size());

        Map<String, List<MemberInfoEntity>> memberMap = list.stream().collect(Collectors.groupingBy(MemberInfoEntity::getAreaCode));


        List<String> areaCodeList = list.stream().map(MemberInfoEntity::getAreaCode).collect(toList());

        List<String> noRepeatList = areaCodeList.stream().distinct().collect(toList());

        for (String areaCode : noRepeatList) {
            StatisDataItemEntity result = new StatisDataItemEntity();

            result.setId(UUID.randomUUID().toString().replace("-", ""));
            result.setAreaCode(areaCode);
            result.setBusinessType(item.getBusinessType());
            result.setYears(month);
            result.setItemSetId(itemSetId);
            result.setStatisConfigCode(item.getStatisItemCode());
            result.setStatisConfigName(item.getStatisItemName());
            result.setStatisConfigId(item.getId());
            result.setStatisType(item.getStatisType());
            result.setStatisUnit(item.getStatisUnit());
            result.setIsStatisPerson(item.getIsCountPerson());
            result.setIsStatisFamily(item.getIsCountFamily());
            result.setIsSum(item.getIsSum());
            result.setIsValue(item.getIsValue());

            List<MemberInfoEntity> memberGroup = memberMap.get(areaCode);
            Map<String, List<MemberInfoEntity>> familyMap = memberGroup.stream().collect(Collectors.groupingBy(MemberInfoEntity::getFamilyId));
            result.setFamilyCount(familyMap.keySet().size());
            result.setCount(memberGroup.size());
            Double salarySum = memberGroup.stream().mapToDouble(MemberInfoEntity::getSalaryNumber).sum();
            result.setSum(salarySum);
            LocalDateTime ldt = LocalDateTime.now();
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String nowDate = dtf.format(ldt);
            result.setCreateTime(nowDate);

            List<MemberInfoEntity> disabled = memberGroup.stream().filter(o -> o.getDisabled() == 1).collect(Collectors.toList());
            result.setCount1(disabled.size());

            List<MemberInfoEntity> young = memberGroup.stream().filter(o -> o.getYoung() == 1).collect(Collectors.toList());
            result.setCount2(young.size());

            List<MemberInfoEntity> other = memberGroup.stream().filter(o -> o.getOther() == 1).collect(Collectors.toList());
            result.setCount3(other.size());
            paList.add(result);
        }
        return paList;
    }


    public static List<StatisDataItemEntity> getStaticsDataItemEntities(TaAreaPo curTaAreaPo, String month, StatisItemEntity item,
                                                                        AreaUtil areaUtil,
                                                                        StatisDataItemReadDao statisDataItemReadDao
    ) {

        List<StatisDataItemEntity> paList;
        String statisticSql = item.getSqlExpress();
        String[] params = item.getStatisParamNum().split(",");
        for (String param : params) {
            if (param.equals(Constant.Parameter.LEVEL)) {
                statisticSql = statisticSql.replace(param, String.valueOf(curTaAreaPo.getAreaLevel()));
            }
            if (param.equals(Constant.Parameter.TIME)) {
                statisticSql = statisticSql.replace(param,
                        "'" + month.substring(0, 4) + "-" + month.substring(4, 6) + "-01'");
            }
            if (param.equals(Constant.Parameter.AREA)) {
                statisticSql = statisticSql.replace(param, "'" +
                        areaUtil.getValidCode(curTaAreaPo.getAreaCode(), curTaAreaPo.getAreaLevel()) + "'");
            }
            if (param.equals(Constant.Parameter.MONTH)) {
                statisticSql = statisticSql.replace(param, "'" + month + "'");
            }
        }
        logger.info("执行指标，name:{}, code:{}", item.getStatisItemName(), item.getStatisItemCode());
        statisticSql = statisticSql.replace("\n", " ");

        paList = statisDataItemReadDao.queryStatisItem(statisticSql);
        return paList;
    }


    public static Map<String, StatisDataItemEntity> sumResultBasicData(String month, String itemSetId, StatisItemEntity item,
                                                                       List<StatisDataItemEntity> paList,
                                                                       AreaUtil areaUtil,
                                                                       StatisDataItemReadDao statisDataItemReadDao
    ) {

        paList.removeAll(Collections.singletonList(null));
        logger.info("查询到{}条数据", paList.size());

        Map<String, StatisDataItemEntity> mapSuperLevelSummary = new HashMap<String, StatisDataItemEntity>();
        for (StatisDataItemEntity record : paList) {
            if (CommonUtil.invalidArgs(record.getAreaCode())) {
                continue;
            }


            int curLevel = areaUtil.getLevelByAreaCode(record.getAreaCode());

            StatisDataItemEntityBuilder builder = new StatisDataItemEntityBuilder(record);
            builder.init(record.getAreaCode(), curLevel, month, itemSetId);
            builder.setStatisItem(item);


            for (int level = curLevel - 1; level >= Constant.AreaLevel.PROVINCE; level--) {
                String superAreaCode = getSuperLevelAreaCodeOverWrite(record.getAreaCode(), level, statisDataItemReadDao);
//                        areaUtil.getSuperLevelAreaCode(record.getAreaCode(), level);
                if (null == mapSuperLevelSummary.get(superAreaCode)) {
                    builder = new StatisDataItemEntityBuilder(new StatisDataItemEntity());
                    builder.init(superAreaCode, null, month, itemSetId);
                    builder.setStatisItem(item);
                    builder.setData(record);
                    mapSuperLevelSummary.put(superAreaCode, builder.get());
                } else {
                    StatisDataItemEntity superStatisDataItem = mapSuperLevelSummary.get(superAreaCode);
                    superStatisDataItem.add(record);
                }
            }
        }
        return mapSuperLevelSummary;
    }



    public static void clearAndUpdate(Map<String, StatisDataItemEntity> mapSuperLevelSummary, List<StatisDataItemEntity> coList,
                                      TaAreaPo curTaAreaPo, String month, String businessType, String statisConfigCode,
                                      String povertyType,
                                      AreaUtil areaUtil,
                                      StatisDataItemReadDao statisDataItemReadDao) {


        List<String> areaCodes = areaUtil.getNodeTreePathFromRoot(curTaAreaPo.getAreaCode());
        List<StatisDataItemEntity> superAreaStatis = statisDataItemReadDao.getStatistics(areaCodes, month,
                businessType, statisConfigCode, povertyType);

        if (superAreaStatis.size() > 0) {

            Optional<StatisDataItemEntity> curStatistic =
                    superAreaStatis.stream().filter(
                            statistic -> statistic.getAreaCode().equals(curTaAreaPo.getAreaCode())).findFirst();

            if (curStatistic.isPresent()) {
                for (StatisDataItemEntity statistic : superAreaStatis) {
                    if (!statistic.getAreaCode().equals(curTaAreaPo.getAreaCode())) {

                        statistic.sub(curStatistic.get());

                        StatisDataItemEntity curData = mapSuperLevelSummary.get(curTaAreaPo.getAreaCode());
                        if (null != curData)
                            statistic.add(curData);
                        statisDataItemReadDao.updateStatistic(statistic);
                        mapSuperLevelSummary.remove(statistic.getAreaCode());
                    }
                }
            }
        }


        statisDataItemReadDao.delSonAreaStatistics(
                areaUtil.getValidCode(curTaAreaPo.getAreaCode(), curTaAreaPo.getAreaLevel()),
                month, businessType, statisConfigCode, povertyType);

        List<StatisDataItemEntity> listSummary = new ArrayList<>(mapSuperLevelSummary.values());
        logger.info("写入非社区级数据：{}条", listSummary.size());
        List<List<StatisDataItemEntity>> lists = new ArrayList<List<StatisDataItemEntity>>();
        if (listSummary.size() > 0)
            lists.addAll(CommonUtil.fixedGrouping(listSummary, 100));

        if (coList.size() > 0)
            lists.addAll(CommonUtil.fixedGrouping(coList, 100));
        logger.info("写入社区级数据：{}条", coList.size());
        for (List<StatisDataItemEntity> temps : lists)
            statisDataItemReadDao.addStatistics(temps);
    }



    public static String getSuperLevelAreaCodeOverWrite(String areaCode, int level,
                                                        StatisDataItemReadDao statisDataItemReadDao){
        String selfArea = areaCode.substring(4, 9);
        switch (level){
            case Constant.AreaLevel.PROVINCE:
                return areaCode.substring(0, 2) + "0000000000";
            case Constant.AreaLevel.CITY:
                return areaCode.substring(0, 4) + "00000000";
            case Constant.AreaLevel.COUNTY:
                if("00999".equals(selfArea)) {
                    return areaCode.substring(0, 6) + "999000";
                }
                return areaCode.substring(0, 6) + "000000";
            case Constant.AreaLevel.STREET:
                if("00999".equals(selfArea)) {

                    String superCode = statisDataItemReadDao.getSuperLevelByAreaCode(areaCode);
                    if (Strings.isNullOrEmpty(superCode)) {
                        logger.info("{},地区未找到对应的父级编码", areaCode);
                        return areaCode.substring(0, 9) + "000";

                    }
                    return superCode;
                }
                return areaCode.substring(0, 9) + "000";
            case Constant.AreaLevel.COMMUNITY:
                return areaCode.substring(0, 12);
            default:
                return areaCode;
        }
    }
}
